package com.zheng.study.web.shiro.filter;

import com.zheng.study.base.bean.Result;
import com.zheng.study.base.service.common.ResultService;
import com.zheng.study.base.utils.LogUtil;
import com.zheng.study.base.utils.mapper.JsonMapper;
import com.zheng.study.web.shiro.realm.StatelessAuthcToken;
import com.zheng.study.web.shiro.utils.ShiroRequestUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 用户会话的Filter
 * ============================================================================
 * author : fallenpanda
 * createDate:  2018/8/17 。
 * ============================================================================
 */
public class StatelessAuthcFilter extends AccessControlFilter {

	@Autowired
	private ResultService resultService;

	protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
		return false;
	}

	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
		// 生成 Token
		StatelessAuthcToken token = new StatelessAuthcToken();
		token.setUid(ShiroRequestUtil.getRequestHeaderUid((HttpServletRequest) request));
		token.setParams(ShiroRequestUtil.getRequestHeaderUserMap((HttpServletRequest) request));
		token.setToken(ShiroRequestUtil.getRequestHeaderUserSign((HttpServletRequest) request));

		try {
			// 委托给Realm进行登录
			Subject subject = getSubject(request, response);
			subject.login(token);
		} catch (Exception e) {
			String error = null;
			if (e instanceof LockedAccountException){// 锁定的账号
				error = "账号状态异常";
			} else if (e instanceof DisabledAccountException) {// 禁用的账号
				error = "账号状态异常";
			} else if (e instanceof UnknownAccountException){// 错误的账号
				error = "用户名/密码错误";
			} else if (e instanceof ExcessiveAttemptsException){// 登录失败次数过多
				error = "密码输入错误超过5次，请10分钟后再试";
			} else if (e instanceof IncorrectCredentialsException){// 错误的凭证
				error = "用户名/密码错误";
			} else if (e instanceof ExpiredCredentialsException){// 过期的凭证
				error = "用户名/密码错误";
			} else if (e instanceof AuthenticationException){
				error = "您的账号没有访问权限";
			} else {
				error = "账号状态异常";
			}
			String exceptionClassName = (String)request.getAttribute("shiroLoginFailure");
			LogUtil.debug("StatelessAuthcFilter : " + exceptionClassName);
			onLoginFail(response,error); // 登录失败
			return false;
		}
		return true;
	}

	// 默认返回403状态码
	private void onLoginFail(ServletResponse response, String error) throws IOException {
		HttpServletResponse httpResponse = (HttpServletResponse) response;
		httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
		String type = "application/json";
		Result result = resultService.error(HttpStatus.FORBIDDEN, error);
		try {
			httpResponse.setContentType(type + ";charset=UTF-8");
			httpResponse.setHeader("Pragma", "No-cache");
			httpResponse.setHeader("Cache-Control", "no-cache");
			httpResponse.setDateHeader("Expires", 0);
			httpResponse.getWriter().write(JsonMapper.nonEmptyMapper().toJson(result));
			httpResponse.getWriter().flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
